package org.hertsig.magiccardmarket;

import java.io.InputStream;

import org.apache.http.client.methods.HttpGet;
import org.hertsig.magiccardmarket.entities.Articles;
import org.hertsig.magiccardmarket.entities.Articles.Article;
import org.hertsig.magiccardmarket.entities.Games;
import org.hertsig.magiccardmarket.entities.Games.Game;
import org.hertsig.magiccardmarket.entities.Metaproducts;
import org.hertsig.magiccardmarket.entities.Metaproducts.Metaproduct;
import org.hertsig.magiccardmarket.entities.Products;
import org.hertsig.magiccardmarket.entities.Products.Product;
import org.hertsig.magiccardmarket.entities.User;
import org.hertsig.magiccardmarket.xml.XmlMarshaller;

import com.google.common.collect.Iterables;

public class MarketplaceApi extends ApiBase {
	public MarketplaceApi(MagicCardMarketApi api) {
		super(api);
	}
	
	public Iterable<Game> games() {
		return XmlMarshaller.unmarshal(api.executeAndGet(new HttpGet(api.games())), Games.class);
	}
	
	public Metaproduct metaproduct(String metaproductId) {
		InputStream stream = api.executeAndGet(new HttpGet(api.metaproduct(metaproductId)));
		return Iterables.getOnlyElement(XmlMarshaller.unmarshal(stream, Metaproducts.class));
	}
	
	/**
	 * Finds the metaproduct with the specified name
	 * @param cardName The exact card name, case insensitive
	 * @param gameId Game id from {@link org.hertsig.magiccardmarket.MagicCardMarketApi.Game}
	 * @param languageId Language id from {@link org.hertsig.magiccardmarket.MagicCardMarketApi.Language}
	 * @return the {@link Metaproduct} with the specified name, or null if no product was found
	 */
	public Metaproduct findMetaproduct(String cardName, int gameId, int languageId) {
		InputStream stream = api.executeAndGet(new HttpGet(api.findMetaproduct(cardName, gameId, languageId)));
		Metaproduct response = Iterables.getOnlyElement(XmlMarshaller.unmarshal(stream, Metaproducts.class), null);
		return response == null || response.getIdMetaproduct() == null ? null : response;
	}
	
	public Product product(String productId) {
		InputStream stream = api.executeAndGet(new HttpGet(api.product(productId)));
		return Iterables.getOnlyElement(XmlMarshaller.unmarshal(stream, Products.class));
	}
	
	/**
	 * Searches for products that match the given search string
	 * @param search The name, or a part of it,
	 * @param gameId Game id from {@link org.hertsig.magiccardmarket.MagicCardMarketApi.Game}
	 * @param languageId Language id from {@link org.hertsig.magiccardmarket.MagicCardMarketApi.Language}
	 * @param exact if true, searches for exact names only (for example "fores" won't match Forest cards)
	 * @return the {@link Product}s matched by the search. Note that iterating over this collection will send requests
	 * to the API each time, so if you need to iterate multiple times you should probably copy the contents over first.
	 */
	public PartialContentIterable<Product> findProduct(String search, int gameId, int languageId, boolean exact) {
		return new PartialContentIterable<>(Products.class, 
				(nextStartIndex) -> api.execute(new HttpGet(api.findProducts(search, gameId, languageId, exact, nextStartIndex))));
	}
	
	/**
	 * Get all articles for the given product id
	 * @return the {@link Article}s matched by the search. Note that iterating over this collection will send requests
	 * to the API each time, so if you need to iterate multiple times you should probably copy the contents over first.
	 */
	public PartialContentIterable<Article> articles(String productId) {
		return new PartialContentIterable<>(Articles.class, 
				(nextStartIndex) -> api.execute(new HttpGet(api.articles(productId, nextStartIndex))));
	}
	
	public User user(String userId) {
		return XmlMarshaller.unmarshal(api.executeAndGet(new HttpGet(api.user(userId))), User.class);
	}
}
